package com.nanhai.buddhist.college.module.study.framework.datapermission;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.nanhai.buddhist.college.framework.common.enums.UserTypeEnum;
import com.nanhai.buddhist.college.framework.common.util.json.JsonUtils;
import com.nanhai.buddhist.college.framework.datapermission.core.rule.DataPermissionRule;
import com.nanhai.buddhist.college.framework.mybatis.core.dataobject.BaseDO;
import com.nanhai.buddhist.college.framework.mybatis.core.util.MyBatisUtils;
import com.nanhai.buddhist.college.framework.security.core.LoginUser;
import com.nanhai.buddhist.college.framework.security.core.util.SecurityFrameworkUtils;
import com.nanhai.buddhist.college.module.system.api.user.AdminUserApi;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.Duration;
import java.util.*;

import static com.nanhai.buddhist.college.framework.common.util.collection.CollectionUtils.convertList;


@Slf4j
@Component
public class SchoolRoleDataPermissionRule implements DataPermissionRule {

    protected static final String CONTEXT_KEY = SchoolRoleDataPermissionRule.class.getSimpleName();

    public static final String USER_DATA_ROLE = "user_data_role_";
    public static final String USER_DATA = "user_data_";
    public static final String USER_COLLEGE_IDS = "user_collegeIds_";
    public static final String USER_DEPARTMENT_IDS = "user_departmentIds_";
    public static final String USER_PROFESSION_IDS = "user_professionIds_";
    public static final String USER_CLASSES_IDS = "user_classesIds_";

    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @PostConstruct
    private void init() {
        this.addTableAndColumn("t_study_additional_courses", "college_id", 0);
        this.addTableAndColumn("t_study_plan", "colleges_id",0);
        this.addTableAndColumn("t_study_additional_courses_class", "classes_id", 3);
        this.addTableAndColumn("t_study_additional_courses_student", "classes_id", 3);

//
//        this.addTableAndColumn("t_school_departments", "college_id");
//        this.addTableAndColumn("t_teacher_teachers", "college_id");
//        this.addTableAndColumn("t_teacher_remuneration", "college_id");
//        this.addTableAndColumn("t_accommodation_reside", "college_id");
//        this.addTableAndColumn("t_accommodation_room", "college_id");
//        this.addTableAndColumn("t_school_professions", "departments_id");
//        this.addTableAndColumn("t_school_classes", "profession_id");
//        this.addTableAndColumn("t_student_roll", "classes_id");
//        this.addTableAndColumn("t_classroom_info", "classes_id");
//        this.addTableAndColumn("t_classroom_info", "department_id");
//        this.addTableAndColumn("t_student_reward_punish_record", "classes_id");
    }

    private final Map<String, String> COLUMNS = new HashMap<>();

    private final Set<String> TABLE_NAMES = new HashSet<>();

    private final Map<String, Integer> DATA_TYPE = new HashMap<>();

    @Override
    public Set<String> getTableNames() {
        return TABLE_NAMES;
    }

    @Override
    public Expression getExpression(String tableName, Alias tableAlias) {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null) {
            return null;
        }
        if (ObjectUtil.notEqual(loginUser.getUserType(), UserTypeEnum.ADMIN.getValue())) {
            return null;
        }
        String userId = loginUser.getId();


        // 判断是否有更新
        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        String user_data_time = stringStringValueOperations.get(USER_DATA + userId);
        String self_data = stringStringValueOperations.get(USER_DATA_ROLE);
        if (!StringUtils.equals(user_data_time, self_data) && Objects.nonNull(self_data)) {
            adminUserApi.initUserCollegeData(userId);
        }
        stringStringValueOperations.set(USER_DATA_ROLE + userId, user_data_time, Duration.ofDays(30));

        String collegeId = stringStringValueOperations.get(USER_COLLEGE_IDS + userId);
        String departmentId = stringStringValueOperations.get(USER_DEPARTMENT_IDS + userId);
        String professionId = stringStringValueOperations.get(USER_PROFESSION_IDS + userId);
        String classesId = stringStringValueOperations.get(USER_CLASSES_IDS + userId);


        if (Objects.isNull(collegeId)) {
            return null;
        }


        Set<String> collegeIds = JsonUtils.parseObject(collegeId, Set.class);
        Set<String> departmentIds = JsonUtils.parseObject(departmentId, Set.class);
        Set<String> professionIds = JsonUtils.parseObject(professionId, Set.class);
        Set<String> classesIds = JsonUtils.parseObject(classesId, Set.class);

        if (Objects.isNull(collegeIds) || collegeIds.isEmpty()) {
            return null;
        }

        String columnName = COLUMNS.get(tableName);
        if (StrUtil.isEmpty(columnName)) {
            return null;
        }

        Integer data_type = DATA_TYPE.get(tableName);
        Set<String> whereData = new HashSet<>();
        switch (data_type) {
            case 0:
                whereData.addAll(collegeIds);
                break;
            case 1:
                whereData.addAll(departmentIds);
                break;
            case 2:
                whereData.addAll(professionIds);
                break;
            case 3:
                whereData.addAll(classesIds);
                break;
        }

        if (whereData.isEmpty()) {
            return new EqualsTo(null, null);
        }


        return new InExpression(MyBatisUtils.buildColumn(tableName, tableAlias, columnName),
                new ExpressionList(convertList(whereData, StringValue::new)));
    }


    public void addTableAndColumn(String tableName, String columnName, Integer type) {
        COLUMNS.put(tableName, columnName);
        TABLE_NAMES.add(tableName);
        DATA_TYPE.put(tableName, type);

    }


//    @DataPermission(enable = false)
//    private Set<String> getClassesIds(Set<String> collegeIds) {
//        List<CollegeAndClassesDO> classesInfoDOS = classesMapper.selectClassesIdByCollege(collegeIds);
//        return convertSet(classesInfoDOS, CollegeAndClassesDO::getClassesId);
//    }


}
